package com.manage.modules.service.impl;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.manage.common.constant.UserConstants;
import com.manage.common.core.domain.TreeSelect;
import com.manage.common.core.domain.entity.SysDept;
import com.manage.common.exception.CustomException;
import com.manage.modules.domain.TBaseArea;
import com.manage.modules.domain.TreeSelectModel;
import com.manage.modules.mapper.TBaseAreaMapper;
import com.manage.modules.service.ITBaseAreaService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 区域信息Service业务层处理
 *
 * @author xu
 * 2021/8/11 15:02
 */
@Service
public class TBaseAreaServiceImpl extends ServiceImpl<TBaseAreaMapper, TBaseArea> implements ITBaseAreaService {

    /**
     * 得到子节点列表
     */
    private List<TBaseArea> getChildList(List<TBaseArea> list, TBaseArea t) {
        List<TBaseArea> tlist = new ArrayList<>();
        for (TBaseArea n : list) {
            if (Validator.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getAreaId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<TBaseArea> list, TBaseArea t) {
        return getChildList(list, t).size() > 0;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<TBaseArea> list, TBaseArea t) {
        // 得到子节点列表
        List<TBaseArea> childList = getChildList(list, t);
        t.setChildren(childList);
        for (TBaseArea tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    @Override
    public List<TBaseArea> buildAreaTree(List<TBaseArea> areas) {
        List<TBaseArea> returnList = new ArrayList<>();
        List<Long> tempList = new ArrayList<>();
        for (TBaseArea area : areas) {
            tempList.add(area.getAreaId());
        }
        for (TBaseArea area : areas) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(area.getParentId())) {
                recursionFn(areas, area);
                returnList.add(area);
            }
        }
        if (returnList.isEmpty()) {
            returnList = areas;
        }
        return returnList;
    }

    @Override
    public List<TreeSelectModel> buildAreaTreeSelect(List<TBaseArea> areas) {
        List<TBaseArea> areaTrees = buildAreaTree(areas);
        return areaTrees.stream().map(TreeSelectModel::new).collect(Collectors.toList());
    }

    @Override
    public TBaseArea selectAreaById(Long areaId) {
        return getById(areaId);
    }

    @Override
    public boolean hasChildByAreaId(Long areaId) {
        int result = count(new LambdaQueryWrapper<TBaseArea>()
                .eq(TBaseArea::getParentId, areaId)
                .last("limit 1"));
        return result > 0;
    }

    @Override
    public int deleteAreaById(Long areaId) {
        return baseMapper.deleteById(areaId);
    }

    @Override
    public int selectNormalChildrenAreaById(Long areaId) {
        return count(new LambdaQueryWrapper<TBaseArea>()
                .eq(TBaseArea::getAreaState, 0)
                .apply("find_in_set({0}, ancestors)", areaId));
    }

    @Override
    public int updateArea(TBaseArea baseArea) {
        TBaseArea newParentArea = getById(baseArea.getParentId());
        TBaseArea oldArea = getById(baseArea.getAreaId());
        if (Validator.isNotNull(newParentArea) && Validator.isNotNull(oldArea)) {
            String newAncestors = newParentArea.getAncestors() + "," + newParentArea.getAreaId();
            String oldAncestors = oldArea.getAncestors();
            baseArea.setAncestors(newAncestors);
            updateAreaChildren(baseArea.getAreaId(), newAncestors, oldAncestors);
        }
        int result = baseMapper.updateById(baseArea);
        if (UserConstants.DEPT_NORMAL.equals(baseArea.getAreaState() + "")) {
            // 如果该区域是启用状态，则启用该区域的所有上级区域
            updateParentAreaStatus(baseArea);
        }
        return result;
    }

    /**
     * 修改该区域的父级区域状态
     *
     * @param baseArea 当前区域
     */
    private void updateParentAreaStatus(TBaseArea baseArea) {
        baseArea = getById(baseArea.getAreaId());
        update(null, new LambdaUpdateWrapper<TBaseArea>()
                .set(baseArea.getAreaState() != null,
                        TBaseArea::getAreaState, baseArea.getAreaState())
                .in(TBaseArea::getAreaId, Arrays.asList(baseArea.getAncestors().split(","))));
    }

    /**
     * 修改子元素关系
     *
     * @param areaId       被修改的区域ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateAreaChildren(Long areaId, String newAncestors, String oldAncestors) {
        List<TBaseArea> children = list(new LambdaQueryWrapper<TBaseArea>()
                .apply("find_in_set({0},ancestors)", areaId));
        for (TBaseArea child : children) {
            child.setAncestors(child.getAncestors().replace(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            updateBatchById(children);
        }
    }

    @Override
    public int insertArea(TBaseArea baseArea) {
        TBaseArea info = getById(baseArea.getParentId());
        // 如果父节点不为正常状态,不允许新增子节点
        if (1 == info.getAreaState()) {
            throw new CustomException("区域停用，不允许新增");
        }
        baseArea.setAncestors(info.getAncestors() + "," + baseArea.getParentId());
        return baseMapper.insert(baseArea);
    }

    @Override
    public List<TBaseArea> selectAreaList(TBaseArea baseArea) {
        LambdaQueryWrapper<TBaseArea> lqw = Wrappers.lambdaQuery();
        lqw
                .eq(baseArea.getParentId() != null && baseArea.getParentId() != 0, TBaseArea::getParentId, baseArea.getParentId())
                .eq(baseArea.getAreaState() != null, TBaseArea::getAreaState, baseArea.getAreaState())
                .like(StrUtil.isNotBlank(baseArea.getAreaName()), TBaseArea::getAreaName, baseArea.getAreaName())
                .orderByAsc(TBaseArea::getOrderNum)
                .orderByAsc(TBaseArea::getParentId);
        return list(lqw);
    }

    @Override
    public String checkAreaNameUnique(TBaseArea baseArea) {
        long areaId = Validator.isNull(baseArea.getAreaId()) ? -1L : baseArea.getAreaId();
        TBaseArea info = getOne(new LambdaQueryWrapper<TBaseArea>()
                .eq(TBaseArea::getAreaName, baseArea.getAreaName())
                .eq(TBaseArea::getParentId, baseArea.getParentId())
                .last("limit 1"));
        if (Validator.isNotNull(info) && info.getAreaId() != areaId) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }
}
